#pragma once
#ifdef _WIN32
#ifndef ___MOD_MEMORY_DETAIL_HPP
#define ___MOD_MEMORY_DETAIL_HPP
#include "../config.hpp"
#include <windows.h>
namespace __memory_detail
{
	template<typename T>
	struct item_return { using type = T&&; };

	template<typename T>
	inline typename item_return<T>::type convert(T&& arg) { return static_cast<T&&>(arg); }

	//INT8
	template<>
	struct item_return<char&> { using type = INT_PTR; };
	template<>
	inline typename item_return<char&>::type convert<char&>(char& arg) { return static_cast<INT_PTR>(arg); }
	template<>
	struct item_return<char> { using type = INT_PTR; };
	template<>
	inline typename item_return<char>::type convert<char>(char&& arg) { return static_cast<INT_PTR>(arg); }
	//INT16
	template<>
	struct item_return<short&> { using type = INT_PTR; };
	template<>
	inline typename item_return<short&>::type convert<short&>(short& arg) { return static_cast<INT_PTR>(arg); }
	template<>
	struct item_return<short> { using type = INT_PTR; };
	template<>
	inline typename item_return<short>::type convert<short>(short&& arg) { return static_cast<INT_PTR>(arg); }
	//INT32
	template<>
	struct item_return<int&> { using type = INT_PTR; };
	template<>
	inline typename item_return<int&>::type convert<int&>(int& arg) { return static_cast<INT_PTR>(arg); }
	template<>
	struct item_return<int> { using type = INT_PTR; };
	template<>
	inline typename item_return<int>::type convert<int>(int&& arg) { return static_cast<INT_PTR>(arg); }
	//INT64
	template<>
	struct item_return<__int64&> { using type = INT_PTR; };
	template<>
	inline typename item_return<__int64&>::type convert<__int64&>(__int64& arg) { return static_cast<INT_PTR>(arg); }
	template<>
	struct item_return<__int64> { using type = INT_PTR; };
	template<>
	inline typename item_return<__int64>::type convert<__int64>(__int64&& arg) { return static_cast<INT_PTR>(arg); }
	//LPVOID
	template<>
	struct item_return<void*&> { using type = INT_PTR; };
	template<>
	inline typename item_return<void*&>::type convert<void*&>(void*& arg) { return (INT_PTR)(arg); }
	template<>
	struct item_return<void*> { using type = INT_PTR; };
	template<>
	inline typename item_return<void*>::type convert<void*>(void*&& arg) { return (INT_PTR)(arg); }


	struct read_struct
	{
		inline unsigned char int8()
		{
			unsigned char v = 0;
			ReadProcessMemory(m_hProcess, (void*)m_Pointer, (void*)&v, sizeof(v), 0);
			return v;
		}
		inline unsigned short int16()
		{
			unsigned short v = 0;
			ReadProcessMemory(m_hProcess, (void*)m_Pointer, (void*)&v, sizeof(v), 0);
			return v;
		}
		inline unsigned int int32()
		{
			unsigned int v = 0;
			ReadProcessMemory(m_hProcess, (void*)m_Pointer, (void*)&v, sizeof(v), 0);
			return v;
		}
		inline unsigned __int64 int64()
		{
			unsigned __int64 v = 0;
			ReadProcessMemory(m_hProcess, (void*)m_Pointer, (void*)&v, sizeof(v), 0);
			return v;
		}
		inline float float32()
		{
			float v = 0;
			ReadProcessMemory(m_hProcess, (void*)m_Pointer, (void*)&v, sizeof(v), 0);
			return v;
		}
		inline double float64()
		{
			double v = 0;
			ReadProcessMemory(m_hProcess, (void*)m_Pointer, (void*)&v, sizeof(v), 0);
			return v;
		}
		inline std::string string(size_t size = 256)
		{
			std::string res(size, 0);
			ReadProcessMemory(m_hProcess, (void*)m_Pointer, (void*)res._Unchecked_begin(), size, 0);
			size_t off = res.find('\0');
			if (off != std::string::npos)
			{
				res.erase(res.begin() + off, res.end());
			}
			return res;
		}
		inline std::wstring wstring(size_t size = 256)
		{
			std::wstring res(size, 0);
			ReadProcessMemory(m_hProcess, (void*)m_Pointer, (void*)res._Unchecked_begin(), size, 0);
			size_t off = res.find('\0000');
			if (off != std::wstring::npos)
			{
				res.erase(res.begin() + off, res.end());
			}
			return res;
		}
		inline mod::binary binary(size_t size = 256)
		{
			mod::binary res(size, (unsigned char)0);
			ReadProcessMemory(m_hProcess, (void*)m_Pointer, (void*)res._Unchecked_begin(), size, 0);
			return res;
		}
		inline read_struct(HANDLE hProcess, INT_PTR Pointer) :m_hProcess(hProcess), m_Pointer(Pointer) {}
		HANDLE m_hProcess;
		INT_PTR m_Pointer;
	};
	struct write_struct
	{
		inline bool int8(unsigned char value)
		{
			return WriteProcessMemory(m_hProcess, (void*)m_Pointer, (void*)&value, sizeof(value), 0);
		}
		inline bool int16(unsigned short value)
		{
			return WriteProcessMemory(m_hProcess, (void*)m_Pointer, (void*)&value, sizeof(value), 0);
		}
		inline bool int32(unsigned int value)
		{
			return WriteProcessMemory(m_hProcess, (void*)m_Pointer, (void*)&value, sizeof(value), 0);
		}
		inline bool int64(unsigned __int64 value)
		{
			return WriteProcessMemory(m_hProcess, (void*)m_Pointer, (void*)&value, sizeof(value), 0);
		}
		inline bool float32(float value)
		{
			return WriteProcessMemory(m_hProcess, (void*)m_Pointer, (void*)&value, sizeof(value), 0);
		}
		inline bool float64(double value)
		{
			return WriteProcessMemory(m_hProcess, (void*)m_Pointer, (void*)&value, sizeof(value), 0);
		}
		inline bool string(std::string value)
		{
			char* data = value._Unchecked_begin();
			return WriteProcessMemory(m_hProcess, (void*)m_Pointer, (void*)data, lstrlenA(data), 0);
		}
		inline bool wstring(std::wstring value)
		{
			wchar_t* data = value._Unchecked_begin();
			return WriteProcessMemory(m_hProcess, (void*)m_Pointer, (void*)data, lstrlenW(data) * 2, 0);
		}
		inline bool binary(mod::binary value)
		{
			return WriteProcessMemory(m_hProcess, (void*)m_Pointer, (void*)value._Unchecked_begin(), value.size(), 0);
		}
		inline write_struct(HANDLE hProcess, INT_PTR Pointer) :m_hProcess(hProcess), m_Pointer(Pointer) {}
		HANDLE m_hProcess;
		INT_PTR m_Pointer;
	};
}
__MOD_BEGIN

__MOD_END
#endif
#endif // WIN32